package com.leo.cloud.common.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * 文件名：TreeUtil.java
 * @create 2020-04-28 15:18
 * @create by Dibbing pan 
 *
 */
public class TreeUtil {
    private static boolean[] isHaveAdd;
//    public static List<Map<String,Object>> getTree(List<Map<String,Object>> dtTree, String pidName, String butName, String keyName, Boolean checkbox,List<String> otherCols,String sortKey,Boolean isAsc) {
//        return getTree(dtTree, pidName, butName, keyName, checkbox, (List) null,sortKey,isAsc);
//    }

    public static void main(String[] args) {
        Map<String,Object> m1 = new HashMap<>(2);
        m1.put("sortKey", 1);
        m1.put("name", "name1");
        m1.put("id", "id=1");
        m1.put("pid", null);
        m1.put("code", "code1");
        m1.put("code1", "code1");
        m1.put("code4", "444");
        m1.put("code3", "333");
        m1.put("code2", "222");
        Map<String,Object> m2 = new HashMap<>(2);
        m2.put("sortKey", -1);
        m2.put("name", "name2");
        m2.put("id", "id=2");
        m2.put("pid",null);
        m2.put("code", "code2");
        m2.put("code1",null);
        Map<String,Object> m3 = new HashMap<>(2);
        m3.put("sortKey",10);
        m3.put("name","name3");
        m3.put("id","id=3");
        m3.put("pid",null);
        m3.put("code","code=3");
        m3.put("code1",null);

        List<Map<String,Object>> list = new ArrayList<>(4);
        list.add(m1);
        list.add(m2);
        list.add(m3);
        String sortKey="sortKey";
        System.out.println(JSON.toJSONString(sort(list,sortKey,true) ));


        System.out.println("--------------------格式化tree--------------->");

        Map<String,Object> m31 = new HashMap<>(2);
        m31.put("sortKey",11);
        m31.put("name","name31");
        m31.put("id","31");
        m31.put("pid","3");
        m31.put("code","31");
        Map<String,Object> m32 = new HashMap<>(2);
        m32.put("sortKey",2);
        m32.put("name","name32");
        m32.put("id","32");
        m32.put("pid","3");
        m32.put("code1","32");
        m32.put("code","32");
        list.add(m31);
        list.add(m32);
        System.out.println(JSON.toJSONString(getTree(list, "pid", "name", "id", false, null, Arrays.asList("code","code1"), "sortKey", true)));
    }
    public static List<Map<String,Object>> getTree(List<Map<String,Object>> dtTree,
                                                   String pidName, String butName, String keyName,
                                                   Boolean checkbox,List<String> checkIds, List<String> otherCols,
                                                   String sortKey,Boolean isAsc) {
        List<Map<String,Object>> listTree = new ArrayList<Map<String,Object>>( );
        isHaveAdd = new boolean[dtTree.size( )];
        for (int i = 0; i < dtTree.size( ); i++) {
            ListIterator<Map<String,Object>> localIterator = dtTree.listIterator(i);
            if (localIterator.hasNext( )) {
                Map<String,Object> map = localIterator.next( );
                if (!isHaveAdd[i]) {
                    String pid = map.get(pidName) != null ? map.get(pidName).toString( ) : "";
                    String id = map.get(keyName) != null ? map.get(keyName).toString( ) : "";
                    if (isRootNode(dtTree, pid, keyName) == -1) {
                        isHaveAdd[i] = true;
                        HashMap<String,Object> propertyTree = new HashMap<String,Object>( );
                        propertyTree.put("label", map.get(butName));
                        propertyTree.put("value", map.get(keyName));
                        if(StringUtils.isNotBlank(sortKey)){
                            propertyTree.put(sortKey, map.get(sortKey));
                        }
                        if (null!=checkbox && checkbox) {
                            propertyTree.put("checked", checkIds.contains(id));
                        }
                        if ((otherCols != null) && !otherCols.isEmpty()) {
                            for(String k:otherCols){
                                propertyTree.put(k, map.get(k));
                            }
                            /*Iterator keys = otherCols.iterator( );
                            while (keys.hasNext( )) {
                                String i$ = (String) keys.next( );
                                propertyTree.put(i$, map.get(i$));
                            }*/
                        }
                        Set<String> arg16 = map.keySet();
                        if (!arg16.isEmpty()) {
                            for(String k:arg16){
                                if ((!k.equals(butName)) && (!k.equals(keyName))) {
                                    propertyTree.put(k, map.get(k));
                                }
                            }
                            /*Iterator arg17 = arg16.iterator( );
                            while (arg17.hasNext( )) {
                                Object s = arg17.next( );
                                if ((!s.toString( ).equals(butName)) && (!s.toString( ).equals(keyName))) {
                                    propertyTree.put(s.toString( ), map.get(s));
                                }
                            }*/
                        }
                        if (judgeIsParentNode(dtTree, id, pidName)) {
                            propertyTree.put("children", addChildNode(dtTree, id, pidName, butName, keyName, checkbox,checkIds,sortKey,isAsc));
                            propertyTree.put("leaf", false);
                        } else {
                            propertyTree.put("children", "");
                            propertyTree.put("leaf", true);
                        }
                        listTree.add(propertyTree);
                    }
                }
            }
        }
        isAsc=isAsc==null?true:isAsc;
        return sort(listTree,sortKey,isAsc);
    }

    private static List<Map<String,Object>> addChildNode(List<Map<String,Object>> dtTree, String p_tree_node_id, String pidName, String butName, String keyName,
                                                         Boolean checkbox,List<String> checkIds,String sortKey,Boolean isAsc) {
        List<Map<String,Object>> listChild = new ArrayList<Map<String,Object>>( );
        for (int i = 0; i < dtTree.size( ); i++) {
            ListIterator<Map<String,Object>> localIterator = dtTree.listIterator(i);
            if (localIterator.hasNext( )) {
                Map map = localIterator.next( );
                if (!isHaveAdd[i]) {
                    String pid = map.get(pidName) != null ? map.get(pidName).toString( ) : "";
                    String id = map.get(keyName) != null ? map.get(keyName).toString( ) : "";
                    if (pid.equals(p_tree_node_id)) {
                        isHaveAdd[i] = true;
                        HashMap<String,Object> propertyChildTree = new HashMap<String,Object>( );
                        propertyChildTree.put("label", map.get(butName));
                        propertyChildTree.put("value", map.get(keyName));
                        if(StringUtils.isNotBlank(sortKey)){
                            propertyChildTree.put(sortKey, map.get(sortKey));
                        }
                        if (null != checkbox && checkbox) {
                            propertyChildTree.put("checked", checkIds.contains(id));
                        }
                        Set keys = map.keySet( );
                        if (!keys.isEmpty()) {
                            Iterator i$ = keys.iterator( );
                            while (i$.hasNext( )) {
                                Object s = i$.next( );
                                if ((!s.toString( ).equals(butName)) && (!s.toString( ).equals(keyName))) {
                                    propertyChildTree.put(s.toString( ), map.get(s));
                                }
                            }
                        }
                        if (judgeIsParentNode(dtTree, id, pidName)) {
                            propertyChildTree.put("children", addChildNode(dtTree, id, pidName, butName, keyName, checkbox,checkIds,sortKey,isAsc));
                            propertyChildTree.put("leaf", false);
                        } else {
                            propertyChildTree.put("children", "");
                            propertyChildTree.put("leaf", true);
                        }
                        listChild.add(propertyChildTree);
                    }
                }
            }
        }
        if(StringUtils.isNotBlank(sortKey)){
            isAsc=isAsc==null?true:isAsc;
            listChild=sort(listChild,sortKey,isAsc);
        }
        return listChild;
    }

    private static boolean judgeIsParentNode(List<Map<String,Object>> treeDt, String tree_node_id, String pidName) {
        for (int i = 0; i < treeDt.size( ); i++) {
            ListIterator<Map<String,Object>> localIterator = treeDt.listIterator(i);
            if (localIterator.hasNext( )) {
                Map<String,Object> map = localIterator.next( );
                if (!isHaveAdd[i]) {
                    String pid = map.get(pidName) != null ? map.get(pidName).toString( ) : "";
                    if (pid.equals(tree_node_id)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private static int isRootNode(List<Map<String,Object>> treeDt, String tree_node_id, String keyName) {
        for (int i = 0; i < treeDt.size( ); i++) {
            ListIterator<Map<String,Object>> localIterator = treeDt.listIterator(i);
            if (localIterator.hasNext( )) {
                Map<String,Object> map = localIterator.next( );
                String id = map.get(keyName) != null ? map.get(keyName).toString( ) : "";
                if (id.equals(tree_node_id)) {
                    return i;
                }
            }
        }
        return -1;
    }

    private static List<Map<String,Object>> sort(List<Map<String,Object>> list,String sortKey,Boolean isAsc){
        list.sort(new Comparator<Map<String, Object>>( ) {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                if(null != o1.get(sortKey) && null != o2.get(sortKey)){
                    try {
                        int i1=Integer.parseInt(o1.get(sortKey).toString());
                        int i2=Integer.parseInt(o2.get(sortKey).toString());
                        if(i1>i2){
                            return isAsc?1:-1;
                        }else if(i1<i2){
                            return isAsc?-1:1;
                        }
                    }catch (Exception e){}
                }
                return 0;
            }
        });
        return list;
    }
}
